package hooks

import (
	"context"
	"fmt"
	"io"
	"os"
	"strconv"

	log "atomgit.com/atomgit_dev/alog/alogcore"
	"atomgit.com/atomgit_dev/git-hooks/pkg/internal/agitext"
	"google.golang.org/grpc"
)

const (
	PushRuleCheckTimeoutRemind = "推送检查超时，代码库已开启推送规则检查，请分批推送或关闭推送规则检查后再试。"
	PreReceive                 = "pre-receive"
	PostReceive                = "post-receive"
	PackObjects                = "pack-objects"
	PostFetch                  = "post-fetch"
	PreSendPack                = "pre-send-pack"
	PreAutoGC                  = "pre-auto-gc"
)

func Run(hook string, args ...string) int {
	span, ctx := agitext.AGitStartSpanFromEnv(context.Background(), hook)
	defer span.Finish()

	var exitCode int
	var err error
	switch hook {
	case PreReceive:
		exitCode, err = StartPreReceive(ctx)
	case PostReceive:
		exitCode, err = StartPostReceive(ctx)
	case PackObjects:
		exitCode, err = StartPackObjects(ctx, args)
	case PostFetch:
		exitCode, err = StartPostFetch(ctx, args)
	case PreSendPack:
		exitCode, err = StartPreSendPack(ctx)
	case PreAutoGC:
		exitCode, err = StartPreAutoGC(ctx)
	default:
		err = fmt.Errorf("unsupported hook: %q", hook)
		exitCode = 1
	}

	fields := []log.Field{log.NewIntField("exitCode", exitCode), log.NewStringField("hook", hook)}
	if err != nil {
		log.WithError(err).Error(ctx, "hook exec failed", fields...)
	} else {
		log.Info(ctx, "hook exec success", fields...)
	}
	return exitCode
}

func sendFunc(reqWriter io.Writer, stream grpc.ClientStream, stdin io.Reader) func(errC chan error) {
	return func(errC chan error) {
		_, errSend := io.Copy(reqWriter, stdin)
		errClose := stream.CloseSend()
		if errSend != nil {
			errC <- errSend
		} else {
			errC <- errClose
		}
	}
}

func getPushOptionsFromEnv() []string {
	var gitPushOptions []string
	pushOptionCount := os.Getenv("GIT_PUSH_OPTION_COUNT")
	n, err := strconv.Atoi(pushOptionCount)
	if err == nil && n > 0 {
		for i := 0; i < n; i++ {
			gitPushOptions = append(gitPushOptions, os.Getenv(fmt.Sprintf("GIT_PUSH_OPTION_%d", i)))
		}
	}
	return gitPushOptions
}
